package com.zzyl.serve.service.impl;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.*;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.constant.HttpStatus;
import com.zzyl.common.core.page.TableDataInfo;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.StringUtils;
import com.zzyl.common.utils.bean.BeanUtils;
import com.zzyl.serve.domain.Elder;
import com.zzyl.serve.dto.DeviceDetailVo;
import com.zzyl.serve.dto.DeviceDto;
import com.zzyl.serve.vo.DeviceReportDataVo;
import com.zzyl.serve.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.serve.mapper.DeviceMapper;
import com.zzyl.serve.domain.Device;
import com.zzyl.serve.service.IDeviceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * 设备Service业务层处理
 * 
 * @author Lai
 * @date 2025-08-22
 */
@Slf4j
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService {
    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    private IoTDAClient client;

    /**
     * 查询设备
     *
     * @param id 设备主键
     * @return 设备
     */
    @Override
    public Device selectDeviceById(Long id) {
        return deviceMapper.selectById(id);
    }

    /**
     * 查询设备列表
     *
     * @param device 设备
     * @return 设备
     */
    @Override
    public List<Device> selectDeviceList(Device device) {
        return deviceMapper.selectDeviceList(device);
    }

    /**
     * 新增设备
     *
     * @param device 设备
     * @return 结果
     */
    @Override
    public int insertDevice(Device device) {
        return deviceMapper.insert(device);
    }

    /**
     * 修改设备
     *
     * @param device 设备
     * @return 结果
     */
    @Override
    public int updateDevice(Device device) {
        return deviceMapper.updateById(device);
    }

    /**
     * 批量删除设备
     *
     * @param ids 需要删除的设备主键
     * @return 结果
     */
    @Override
    public int deleteDeviceByIds(Long[] ids) {
        return deviceMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除设备信息
     *
     * @param id 设备主键
     * @return 结果
     */
    @Override
    public int deleteDeviceById(Long id) {
        return deviceMapper.deleteById(id);
    }


    /*
     * 同步产品列表
     * */
    @Override
    public void syncProductList() {
        //从物联网平台查询所有产品列表
        ListProductsRequest request = new ListProductsRequest();
        ListProductsResponse response = client.listProducts(request);
        if (response.getHttpStatusCode() != 200) {
            throw new BaseException("物联网接口-同步设备列表失败");
        }
        //将产品缓存到redis中
        redisTemplate.opsForValue().set(CacheConstants.IOT_PRODUCT_LIST_KEY, JSONUtil.toJsonStr(response.getProducts()));
    }

    /**
     * 查询所有产品列表
     **/
    @Override
    public List<ProductVo> allProduct() {
        //从redis中查询产品列表
        String str = (String) redisTemplate.opsForValue().get(CacheConstants.IOT_PRODUCT_LIST_KEY);
        //如果查不到，就返回一个空集合
        if (StringUtils.isEmpty(str)) {
            return new ArrayList<>();
        }
        return JSONUtil.toList(str, ProductVo.class);
    }


    /**
     * 注册设备
    * */
   @Override
   public void registerDevice(DeviceDto deviceDto){
       //判断设备名是否重复
       LambdaQueryWrapper<Device> wrapper = Wrappers.<Device>lambdaQuery()
               .eq(Device::getDeviceName,deviceDto.getDeviceName());
       if(count(wrapper) > 0){
           throw new BaseException("设备名已存在，请重新输入");
       }
       //检测设备标识码是否重复
       wrapper=new LambdaQueryWrapper<Device>()
               .eq(Device::getNodeId,deviceDto.getNodeId());
       if(count(wrapper)>0){
           throw new BaseException("设备标识码已存在,请重新输入");
       }

       //校验是否绑定了同一产品
       wrapper = Wrappers.<Device>lambdaQuery()
               .eq(Device::getProductKey,deviceDto.getProductKey())
               .eq(Device::getLocationType,deviceDto.getLocationType())
               .eq(Device::getPhysicalLocationType,deviceDto.getPhysicalLocationType())
               .eq(Device::getBindingLocation,deviceDto.getBindingLocation());
       if(count(wrapper) > 0){
           throw new BaseException("老人已绑定该产品,请重新选择");
       }


       //iot中新增产品
       AddDeviceRequest request = new AddDeviceRequest();
       AddDevice body = new AddDevice();
       body.withProductId(deviceDto.getProductKey());
       body.withDeviceName(deviceDto.getDeviceName());
       body.withNodeId(deviceDto.getNodeId());


       AuthInfo authInfo = new AuthInfo();
       //利用hutool工具
       String secret =  UUID.randomUUID().toString(true);
       authInfo.withSecret(secret);
       body.setAuthInfo(authInfo);
       request.setBody(body);
       AddDeviceResponse response = client.addDevice(request);

       //设备数据保存到数据库
       /*Device device = new Device();
       BeanUtils.copyProperties(deviceDto, device, "id");*/
       Device device =new Device();
       device = BeanUtil.toBean(deviceDto, Device.class);

       //设备id、设备绑定状态
       device.setIotId(response.getDeviceId());
       //秘钥
       device.setSecret(secret);

       //在数据库中新增设备
       save(device);
   }

   /*
   *查询设备详细
    */
   @Override
    public DeviceDetailVo getInfo(String iotId){
       //先从数据库查找数据
       LambdaQueryWrapper<Device> wrapper = Wrappers.<Device>lambdaQuery()
               .eq(Device::getIotId,iotId);
       Device device = getOne(wrapper);
       if(device == null){
           return null;
       }

       //从华为云ioTDA中查询设备信息
       ShowDeviceRequest request =new ShowDeviceRequest();
       request.setDeviceId(iotId);
       ShowDeviceResponse response = client.showDevice(request);

       //属性拷贝
       DeviceDetailVo vo = new DeviceDetailVo();
       BeanUtils.copyProperties(device, vo);
       vo.setBindingLocation(Long.parseLong(device.getBindingLocation()));
       vo.setDeviceStatus(response.getStatus());
       String activeTime = response.getActiveTime();
       if (StringUtils.isNotEmpty(activeTime)) {
           //将activeTime日期字符串值'2025-08-18T13:09:07.104Z'转换成LocalDateTime对象
           LocalDateTime dateTime = LocalDateTime.parse(activeTime, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
           //dateTime是0时区的时间，转换成北京东8区
           dateTime = dateTime.atZone(ZoneId.of("UTC")).withZoneSameInstant(ZoneId.of("Asia/Shanghai")).toLocalDateTime();
           vo.setActiveTime(dateTime);
       }

       return vo;

   }

   @Override
    public List<DeviceReportDataVo> queryDeviceProperties(String iotId){
       //向互联网发请求 查询设备的影子信息
       ShowDeviceShadowRequest request = new ShowDeviceShadowRequest();
       request.setDeviceId(iotId);
       ShowDeviceShadowResponse response = client.showDeviceShadow(request);
       List<DeviceShadowData> shadow = response.getShadow();
       if(shadow == null  || shadow.isEmpty()){
           return Collections.emptyList();
       }

       //获取设备上报的数据
       Map<String,Object> properties = (Map<String,Object>)shadow.get(0).getReported().getProperties();

       //获取上报的时间
       String eventTimeStr = shadow.get(0).getReported().getEventTime();
       LocalDateTime reportTime = LocalDateTime.parse(eventTimeStr,DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'"));
       LocalDateTime eventTime = reportTime.atZone(ZoneId.of("UTC")).withZoneSameInstant(ZoneId.of("Asia/Shanghai")).toLocalDateTime();


       //封装结果
       List<DeviceReportDataVo> list = new ArrayList<>();
       properties.forEach((prop,value)->{
           DeviceReportDataVo vo = new DeviceReportDataVo();
           vo.setFunctionId(prop);
           vo.setValue(value);
           vo.setEventTime(eventTime);
           list.add(vo);
       });
       return list;
   }


    /**
     * 获取设备的物理模型
     */
   @Override
    public List<ServiceCapability> queryProduct(String productId){
        ShowProductRequest request = new ShowProductRequest();
        request.setProductId(productId);
        ShowProductResponse response = client.showProduct(request);
if( response.getHttpStatusCode()!=200){
    throw new BaseException("查询失败");
}
return response.getServiceCapabilities();
   }

}